package cn.yanxiaohui.service.web.pattern.proxy.jdk.myself;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * 自定义代理类
 */
public class MyProxy {

    static String rt = "\r\t";
    /**
     * @Description 初始化代理类
     * @Author： yanxh<br>
     * @Date 2019/12/9 18:06<br>
     * @Version 1.0<br>
     */
    public static Object newProxyInstance(Class<?> classInfo, MyInvocationHandler h) {
        try{
            // 1.创建java代理类
            Method[] methods = classInfo.getMethods();
            String proxyClass = "package cn.yanxiaohui.service.web.pattern.proxy.jdk.myself;" + rt
                    + "import java.lang.reflect.Method;" + rt
                    + "public class $Proxy0 implements "+classInfo.getName()+"{" + rt
                    + "    private MyInvocationHandler h;" + rt
                    + "    public $Proxy0(MyInvocationHandler h) {" + rt
                    + "        this.h = h;" + rt
                    + "    }" + rt
                    + getMethodString(methods, classInfo)
                    + "}";

            // 2.写入本地文件中
            String fileName = "D:/yxhData/MyProject/yanxiaohui/yxh-service-web/src/main/java/cn/yanxiaohui/service/web/pattern/proxy/jdk/myself/$Proxy0.java";
            File file = new File(fileName);
            FileWriter fw = new FileWriter(file);
            fw.write(proxyClass);
            fw.flush();
            fw.close();

            // 3.将源代码进行编译
            // 获取编译器实例
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            // 获取标准文件管理器实例
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
            Iterable<? extends JavaFileObject> javaFileObjects = fileManager.getJavaFileObjects(fileName);
            JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, fileManager, null, null, null, javaFileObjects);
            //运行编译任务
            compilationTask.call();
            fileManager.close();

            // 4.使用classLoader技术将编译后的文件加载至内存
            LocalClassLoader loader = new LocalClassLoader("D:/yxhData/MyProject/yanxiaohui/yxh-service-web/src/main/java/");
            Class<?> aClass = loader.findClass("cn.yanxiaohui.service.web.pattern.proxy.jdk.myself.$Proxy0");

            // 5.通过构造设置方法增强器
            Constructor<?> constructor = aClass.getConstructor(MyInvocationHandler.class);
            Object o = constructor.newInstance(h);
            return o;

        } catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }




    public static String getMethodString(Method[] methods, Class<?> classInfo){
        String result = "";
        for (Method method : methods) {
            result += "public void " + method.getName() + "() {" + rt
                    + "        try{" + rt
                    + "            Method method = " + classInfo.getName() + ".class.getMethod(\""+method.getName()+"\", new Class[]{});"  + rt
                    + "            h.invoke(this, method, null);" + rt
                    + "        } catch (Throwable e){"  + rt
                    + "            e.printStackTrace();"  + rt
                    + "        }"  + rt
                    + "    }" + rt;

        }

        return result;
    }
}
